<template>
  <div class="openflights-animation">
    <div id="openflights-map" class="map-container"></div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue';
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import XYZ from 'ol/source/XYZ';
import { fromLonLat } from 'ol/proj';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import Feature from 'ol/Feature';
import LineString from 'ol/geom/LineString';
import Point from 'ol/geom/Point';
import { Style, Stroke, Icon } from 'ol/style';

let map: Map | null = null; // 地图实例
let animationId: number | null = null; // 动画帧ID
let vectorLayer: VectorLayer<VectorSource> | null = null; // 航线图层
let planeLayer: VectorLayer<VectorSource> | null = null; // 飞机图标图层

const FLIGHT_COLOR = 'rgba(0,234,255,0.7)'; // 主航线颜色
const FLOW_COLOR = 'rgba(255,255,255,0.7)'; // 流光颜色
const ANIMATION_DURATION = 2000; // 动画周期（毫秒）
const PLANE_ICON =
  'data:image/svg+xml;utf8,<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg"><g><path d="M16 2L18 12H30L18 20L20 30L16 24L12 30L14 20L2 12H14L16 2Z" fill="%2300eaff" stroke="%2300eaff" stroke-width="1.5"/></g></svg>';

let flights: [number, number][][] = []; // 航班数据
let animationProgress = 0; // 动画进度（0~1）

// 读取航班数据，返回二维数组（每条航线的起点和终点经纬度）
async function loadFlights() {
  const response = await fetch('/src/data/openflights/flights.json');
  const data = await response.json();
  return data.flights as [number, number][][];
}

// 计算两点间的插值点（用于动画流动）
function interpolate(start: number[], end: number[], t: number) {
  return [
    start[0] + (end[0] - start[0]) * t,
    start[1] + (end[1] - start[1]) * t,
  ];
}

// 根据当前动画进度，生成所有航线和飞机的要素
function createFlightFeatures(flights: [number, number][][], progress: number) {
  const lineFeatures: Feature[] = [];
  const planeFeatures: Feature[] = [];
  for (const flight of flights) {
    // 经纬度转墨卡托投影
    const start = fromLonLat([flight[0][1], flight[0][0]]);
    const end = fromLonLat([flight[1][1], flight[1][0]]);
    // 当前动画进度（0~1）
    const t = progress;
    // 当前流光/飞机位置
    const current = interpolate(start, end, t);
    // 主航线（整条线）
    const line = new LineString([start, end]);
    lineFeatures.push(new Feature({ geometry: line }));
    // 流光段（只显示一小段高亮线）
    const flowLen = 0.15; // 流光长度百分比
    const t0 = Math.max(0, t - flowLen);
    const flowStart = interpolate(start, end, t0);
    const flowLine = new LineString([flowStart, current]);
    const flowFeature = new Feature({ geometry: flowLine });
    flowFeature.set('isFlow', true); // 标记为流光
    lineFeatures.push(flowFeature);
    // 飞机图标（显示在流光末端）
    const planeFeature = new Feature({ geometry: new Point(current) });
    // 计算飞机朝向角度
    const dx = end[0] - start[0];
    const dy = end[1] - start[1];
    const rotation = Math.atan2(dy, dx);
    planeFeature.set('rotation', rotation);
    planeFeatures.push(planeFeature);
  }
  return { lineFeatures, planeFeatures };
}

// 启动动画主循环
async function startAnimation() {
  flights = await loadFlights(); // 加载航班数据
  const vectorSource = new VectorSource(); // 航线数据源
  const planeSource = new VectorSource(); // 飞机数据源
  // 航线图层，包含主航线和流光段
  vectorLayer = new VectorLayer({
    source: vectorSource,
    style: (feature) => {
      // 流光段样式
      if (feature.get('isFlow')) {
        return new Style({
          stroke: new Stroke({
            color: FLOW_COLOR,
            width: 4,
            lineCap: 'round',
          }),
        });
      }
      // 主航线样式
      return new Style({
        stroke: new Stroke({
          color: FLIGHT_COLOR,
          width: 1.5,
          lineDash: [8, 8],
        }),
      });
    },
  });
  // 飞机图标图层
  planeLayer = new VectorLayer({
    source: planeSource,
    style: (feature) => {
      return new Style({
        image: new Icon({
          src: PLANE_ICON,
          scale: 0.7,
          rotation: feature.get('rotation') || 0,
          rotateWithView: true,
        }),
      });
    },
  });
  map?.addLayer(vectorLayer);
  map?.addLayer(planeLayer);

  // 动画帧函数
  function animate() {
    animationProgress += 16 / ANIMATION_DURATION; // 16ms一帧
    if (animationProgress > 1) animationProgress = 0; // 循环动画
    vectorSource.clear();
    planeSource.clear();
    // 生成当前帧的所有要素
    const { lineFeatures, planeFeatures } = createFlightFeatures(flights, animationProgress);
    vectorSource.addFeatures(lineFeatures);
    planeSource.addFeatures(planeFeatures);
    animationId = requestAnimationFrame(animate);
  }
  animate();
}

// 地图初始化
onMounted(() => {
  map = new Map({
    target: 'openflights-map',
    layers: [
      new TileLayer({
        source: new XYZ({
          url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}',
        }),
      }),
    ],
    view: new View({
      center: fromLonLat([0, 30]), // 世界居中
      zoom: 2,
      projection: 'EPSG:3857',
    }),
  });
  startAnimation();
});

// 组件卸载时清理动画和地图
onUnmounted(() => {
  if (animationId) cancelAnimationFrame(animationId);
  if (map) {
    map.setTarget(undefined);
    map = null;
  }
});
</script>

<style scoped>
.openflights-animation, .map-container {
  width: 100%;
  height: 100%;
  min-height: 100vh;
  background: #0a1a2f;
}
</style> 